/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.inmite.demo.validations.slice;

import static eu.inmite.harmony.lib.validations.form.annotations.RegExp.EMAIL;

import eu.inmite.harmony.lib.validations.form.FormValidator;
import eu.inmite.harmony.lib.validations.form.annotations.DateInFuture;
import eu.inmite.harmony.lib.validations.form.annotations.Joined;
import eu.inmite.harmony.lib.validations.form.annotations.MinLength;
import eu.inmite.harmony.lib.validations.form.annotations.MinValue;
import eu.inmite.harmony.lib.validations.form.annotations.NotEmpty;
import eu.inmite.harmony.lib.validations.form.annotations.RegExp;
import eu.inmite.harmony.lib.validations.form.callback.SimpleErrorPopupCallback;
import eu.inmite.harmony.lib.validations.util.LogUtil;
import eu.inmite.demo.validations.AddressValidator;
import eu.inmite.demo.validations.ResourceTable;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.TextField;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ColorSpace;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * MainAbilitySlice
 */
public class MainAbilitySlice extends AbilitySlice {
    private static final String TAG = MainAbilitySlice.class.getName();

    @Joined(value = {ResourceTable.Id_demo_address1, ResourceTable.Id_demo_address2},
        validator = AddressValidator.class, messageId = ResourceTable.String_validation_address)
    private TextField mEditAddress1;

    @NotEmpty(messageId = ResourceTable.String_validation_valid_email)
    @RegExp(value = EMAIL, messageId = ResourceTable.String_validation_valid_email)
    private TextField mEditEmail;

    @NotEmpty(messageId = ResourceTable.String_validation_name, order = 1)
    @MinLength(value = 3, messageId = ResourceTable.String_validation_name_length, order = 1)
    private TextField mEditName;

    @NotEmpty
    @MinValue(value = 1L, messageId = ResourceTable.String_validation_participants, order = 2)
    private TextField mEditNumberOfParticipants;

    @DateInFuture(messageId = ResourceTable.String_validation_date)
    private Text mTxtDate;

    private AbilitySlice mTarget = this;

    private Button btnLiveValidate;

    private Button btnStopLiveValidate;

    private int mYear;

    private int mMonth;

    private int mDay;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        mEditName = (TextField) findComponentById(ResourceTable.Id_demo_name);
        mEditNumberOfParticipants = (TextField) findComponentById(ResourceTable.Id_demo_participants);
        mEditEmail = (TextField) findComponentById(ResourceTable.Id_demo_email);
        mEditAddress1 = (TextField) findComponentById(ResourceTable.Id_demo_address1);
        mTxtDate = (Text) findComponentById(ResourceTable.Id_demo_date);

        mTxtDate.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showDialog();
            }
        });

        setDate(new GregorianCalendar());

        final Button btnOk = (Button) findComponentById(ResourceTable.Id_demo_ok);
        btnOk.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                validate();
            }
        });

        btnLiveValidate = (Button) findComponentById(ResourceTable.Id_demo_live_validation);
        btnLiveValidate.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                FormValidator.startLiveValidation(mTarget, findComponentById(ResourceTable.Id_demo_layout),
                    new SimpleErrorPopupCallback(getContext(), false));
                btnLiveValidate.setEnabled(false);
                btnStopLiveValidate.setEnabled(true);
            }
        });

        btnStopLiveValidate = (Button) findComponentById(ResourceTable.Id_demo_stop_live_validation);
        btnStopLiveValidate.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                FormValidator.stopLiveValidation(mTarget);
                btnStopLiveValidate.setEnabled(false);
                btnLiveValidate.setEnabled(true);
            }
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    private void setDate(final Calendar cal) {
        final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
        mTxtDate.setText(dateFormat.format(cal.getTime()));
        mTxtDate.setAroundElements(null, null, null, null);
    }

    private void showDialog() {
        CommonDialog dialog = new CommonDialog(getContext());
        ComponentContainer rootLayout = (ComponentContainer) LayoutScatter.getInstance(this)
                .parse(ResourceTable.Layout_date_picker, null, false);
        dialog.setContentCustomComponent(rootLayout);
        DatePicker datePicker = (DatePicker) rootLayout.findComponentById(ResourceTable.Id_picker);
        if(mYear != 0) {
            datePicker.updateDate(mYear, mMonth+1, mDay);
        }
        datePicker.setValueChangedListener(new DatePicker.ValueChangedListener() {
            @Override
            public void onValueChanged(DatePicker datePicker, int year, int month, int day) {
                mYear = year;
                mMonth = month-1;
                mDay = day;
            }
        });
        dialog.setDestroyedListener(new CommonDialog.DestroyedListener() {
            @Override
            public void onDestroy() {
                if(mYear == 0) {
                    return;
                }
                Calendar calendar = new GregorianCalendar();
                calendar.set(mYear, mMonth, mDay);
                setDate(calendar);
            }
        });
        dialog.setButton(2, "ok", new IDialog.ClickedListener() {
            @Override
            public void onClick(IDialog iDialog, int i) {
                dialog.destroy();
            }
        });
        dialog.show();
    }

    private void validate() {
        try {
            Element element = getElement(getContext(), ResourceTable.Media_error);
            final boolean isValid = FormValidator.validate(this, new SimpleErrorPopupCallback(this, true, element));
            if (isValid) {
                ToastDialog toastDialog = new ToastDialog(getContext());
                try {
                    toastDialog.setText(
                        getResourceManager().getElement(ResourceTable.String_validation_success).getString()).show();
                } catch (IOException e) {
                    LogUtil.error(TAG, "IOException " + e.toString());
                } catch (NotExistException e) {
                    LogUtil.error(TAG, "NotExistException " + e.toString());
                } catch (WrongTypeException e) {
                    LogUtil.error(TAG, "WrongTypeException " + e.toString());
                }
            }
        } catch (IOException e) {
            LogUtil.error(TAG, "IOException " + e.toString());
        } catch (NotExistException e) {
            LogUtil.error(TAG, "NotExistException " + e.toString());
        }
    }

    private static Element getElement(Context context, int resid) throws IOException, NotExistException {
        // From context get ResrouceMangager
        ResourceManager rm = context.getResourceManager();

        // Pass resrouceId and get Inputstream
        InputStream inputStream = (InputStream) rm.getResource(resid);

        // Create options to decode bimtap
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        resetOptions(decodingOpts);
        PixelMap pixelMap = decodePixelMap(inputStream, decodingOpts, "image/png");

        return new PixelMapElement(pixelMap);
    }

    private static void resetOptions(ImageSource.DecodingOptions decodingOpts) {
        decodingOpts.desiredSize = new Size(0, 0);
        decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
        decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
        decodingOpts.allowPartialImage = false;
        decodingOpts.desiredColorSpace = ColorSpace.UNKNOWN;
        decodingOpts.rotateDegrees = 0.0F;
        decodingOpts.sampleSize = 1;
    }

    private static PixelMap decodePixelMap(InputStream is, ImageSource.DecodingOptions options, String formatHint)
        throws IOException {
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        srcOpts.formatHint = formatHint;
        ImageSource imageSource = ImageSource.create(is, srcOpts);

        if (imageSource == null) {
            throw new FileNotFoundException();
        }

        return imageSource.createPixelmap(options);
    }
}
